Repository navigation
plan 0015: Drag mode — distance runs without a track - #148
Merged
Merged
Conversation
Coverage — host-testable units📂 Overall coverage
📄 File coverage
|
This was referenced Aug 22, 2026
TheAngryRaven
pushed a commit
that referenced
this pull request
Aug 24, 2026
Three design records landed in the same mass-merge window all claiming plan number 0012. Renumber by merge order into BETA, so the earliest merge keeps the number: #156 0012-download-throughput-regression-deepdive (keeps 0012) #155 0012-led-status-modes -> 0013-led-status-modes #154 0012-tach-rpm-single-pickup -> 0014-tach-rpm-single-pickup Every in-tree citation follows: each line referencing "0012" was attributed to the merge that introduced it via first-parent blame (so prose like "plan 0012" and "pre-0012" lands with the right plan), then rewritten - code comments, CLAUDE.md, CONTRIBUTING.md, the CHANGELOG's two slug citations, the compile-sketch.yml flags-off comment, test comments and test-case names, and plan 0003's superseded-by link. The deepdive's own references stay 0012 untouched. No behavior change; host suite still 567/567. Commit messages citing "plan 0012" remain ambiguous - history cannot be rewritten - but the files they resolve to are now unique. PR #148 (drag mode) also styles itself plan 0011, which profiling holds; it should take 0015, the next free number, when it lands. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MqSstYTWPhm3TZ3PxXs4hk
8 of 13 tasks
Main menu -> Drag -> pick 1/8 Mile / 1000 ft / 1/4 Mile / 1/2 Mile /
1 Mile and the session starts: no track file, no detection. Stage at a
standstill, rollout-style launch (11.25 in past a re-latching standstill
anchor, ET start interpolated between 25 Hz fixes), run ends at the
target distance with interpolated ET + trap speed and a 0-60 split, then
re-arms automatically for the next pass. All passes land in one DOVEX
session with race_mode=DRAG (laps line = run ETs, same trailing-column
scheme as SPRINT).
- New host-tested pure unit drag_timer.{h,cpp}: the whole run state
machine (ARMED/STAGED/LAUNCHED), the distance table, silent aborts
(mid-run standstill, >=2 s fix gap — also how queue-creep phantom
launches self-cancel), 14 doctest cases.
- Sketch glue mirrors sprint: dragTimer != nullptr IS drag mode, drag
branch first in every activeTimer*() helper, run capture on the
run-count edge, trackDetected latched, idle-grace re-arm on each run
AND each fresh STAGED latch.
- UI: Drag main-menu row, PAGE_DRAG_DISTANCE picker (scrolling window),
drag branches on the lap-time/pace/best pages (live ET, *staged*,
trap/0-60 subtext, live 0-60 readout), LED pace pip suppressed between
runs like sprint.
- Sim: golden walk updated for the new menu row + a picker fixture;
goldens regenerated; soak/determinism/goldens/oracles all pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKa62h4fhn61pKn1LygrMK
TheAngryRaven
force-pushed
the
claude/drag-mode-planning-mggk0b
branch
from
August 26, 2026 00:28
73019ef to
64246e7
Compare
Six findings from the branch review, all fixed: - Time base: the glue fed getGpsTimeInMilliseconds() (time-of-day, wraps to zero at UTC midnight — evening sessions) into a unit whose contract says epoch ms. Both call sites now feed getGpsUnixTimestampMillis(), and the unit's non-monotonic guard resyncs on a backwards step instead of rejecting every subsequent fix — one step used to wedge the drag timer for the rest of the session. - Launch edge: a >=2 s fix gap while STAGED now re-stages instead of evaluating the launch, so a launch that happened inside a GPS dropout can't interpolate its ET start back to a parked-car fix. - Prove-out gate: a launch must reach 15 mph within 5 s of the ET start or the run is silently abandoned — a wave-off driven to the pits at 4 mph never holds the sub-2 mph standstill abort and used to record 660 ft of pit road as a ~90 s "run". - activeTimerTotalDistance() converts the drag branch to meters, matching every other branch of the accessor. - distanceFeet() delegates to the haversine unit (x 5280) instead of carrying a second copy of the formula and Earth radius. - The seconds.hundredths split rendering is now one function (displayPrintSplitSeconds) shared by the results subtext and the pace page's live 0-60 readout. Five new regression tests cover the wedge recovery, the staged-gap launch, the wave-off, a slow-but-real pass, and duplicate timestamps. Plan 0015 doc + CLAUDE.md constants updated to match. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BKa62h4fhn61pKn1LygrMK
6 of 14 tasks
11 of 18 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Drag mode: main menu → Drag → pick a distance (1/8 Mile, 1000 ft, 1/4 Mile, 1/2 Mile, 1 Mile) and the session starts — no track file, no detection. The device stages at a standstill, starts the clock rollout-style (11.25 in of movement past a re-latching standstill anchor, ET start interpolated between 25 Hz fixes), and ends the run at the target distance with an interpolated ET + trap speed and a 0-60 mph split. It re-arms automatically when the car stops, so a whole day of passes lands in one DOVEX session (
race_mode=DRAG, laps line = run ETs — same backwards-compatible trailing-column scheme as SPRINT; trap/0-60 stay out of the frozen header since the 25 Hz rows carry speed).The run state machine is a new host-tested pure unit,
drag_timer.{h,cpp}: staging (≤1 mph held 1 s, anchor = re-latching running mean so staging-lane GPS drift can't fake a launch), launch (rollout + ≥2 mph, with a ≥2 s fix-gap guard on the launch edge so a launch inside a GPS dropout can't anchor its ET to a parked-car fix), a prove-out gate (reach 15 mph within 5 s of the ET start or the run is abandoned — a wave-off driven to the pits is not a pass), chord-distance accumulation, and silent aborts (3 s mid-run standstill, ≥2 s fix gap) — which is also how queue-creep phantom launches self-cancel. Time base is Unix epoch ms (getGpsUnixTimestampMillis()), never the time-of-day clock that wraps at UTC midnight, and a backwards time step aborts + resyncs rather than wedging the stream. The sketch keeps only sprint-style glue:dragTimer != nullptrIS drag mode, drag branch first in everyactiveTimer*()helper, run capture on the run-count edge, and the auto-idle grace re-arms on each completed run and each fresh stage so a staging queue never idles the session out. Design record indocs/plans/0015-drag-mode.md.UI: new Drag main-menu row +
PAGE_DRAG_DISTANCEpicker (scrolling 3-row window, Back row); the Current Lap / Pace / Best Lap pages branch for drag (live ET,*staged*/*waiting*, trap/0-60 subtext, live 0-60 readout); the LED pace pip is suppressed between runs like sprint.Rebased onto current BETA (post-4.1.0 cut) and renumbered from the colliding plan 0011 to plan 0015. A full self-review of the branch produced 6 findings (3 correctness — the midnight time-base wedge, the launch-edge gap, the wave-off junk run — plus a feet/meters accessor inconsistency, a duplicated haversine, and duplicated 0-60 formatting); all 6 are fixed in the second commit, each with a regression test where testable.
Follow-up outside this repo: the webapp will want a
DRAGcase in its race_mode loader (old viewers degrade gracefully to "unknown mode with a runs line").Type of change
How it was verified
ctest --test-dir tests/build) — 587 cases on the rebased tree, including 19drag_timercases (analytic launch/ET/trap/0-60 interpolation, anchor-drift and jitter immunity, abort paths, re-arm cycles, backwards-time-step recovery, staged-gap launch, wave-off prove-out, distance-table goldens)clang-tidyclean — left to CIBETA)Checklist
CHANGELOG.mdupdated under[Unreleased](if user-visible)ARCHITECTURE.md/CLAUDE.mdupdated (if a module or interface changed)tests/Related issues
None — design record:
docs/plans/0015-drag-mode.md.🤖 Generated with Claude Code
https://claude.ai/code/session_01BKa62h4fhn61pKn1LygrMK